package com.kexio.user.service.impl;

import java.time.LocalDateTime;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.kexio.common.enums.StatusEnum;
import com.kexio.common.exception.BusinessException;
import com.kexio.common.utils.ValidationUtils;
import com.kexio.user.entity.Menu;
import com.kexio.user.entity.Permission;
import com.kexio.user.entity.Role;
import com.kexio.user.entity.RoleMenu;
import com.kexio.user.entity.RolePermission;
import com.kexio.user.entity.User;
import com.kexio.user.mapper.MenuMapper;
import com.kexio.user.mapper.PermissionMapper;
import com.kexio.user.mapper.RoleMapper;
import com.kexio.user.mapper.RolePermissionMapper;
import com.kexio.user.mapper.UserMapper;
import com.kexio.user.mapper.UserRoleMapper;
import com.kexio.user.service.PermissionSyncService;
import com.kexio.user.service.RoleService;
import com.kexio.user.service.UserService;

/**
 * 角色服务实现类
 * 
 * 提供角色管理的核心业务逻辑实现
 * 
 * @author Kexio Team
 * @since 1.0.0
 */
@Service
public class RoleServiceImpl implements RoleService {
    
    private static final Logger logger = LoggerFactory.getLogger(RoleServiceImpl.class);
    
    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private UserRoleMapper userRoleMapper;
    @Autowired
    private UserService userService;
    
    @Autowired
    private PermissionSyncService permissionSyncService;
    
    @Autowired(required = false)
    private com.kexio.user.service.PermissionVersionService permVersionService;

    // 可选依赖
    @Autowired
    private PermissionMapper permissionMapper;
    @Autowired(required = false)
    private MenuMapper menuMapper;
    @Autowired(required = false)
    private UserMapper userMapper;
    @Autowired
    private RolePermissionMapper rolePermissionMapper;
    
    @Autowired(required = false)
    private com.kexio.auth.cache.CacheInvalidationService cacheInvalidationService;
    
    // ✅ 精简JWT架构：权限同步服务
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Role createRole(Role role) {
        ValidationUtils.notNull(role, "角色信息不能为空");
        
        // 统一由租户拦截器处理租户字段，不在此处做必填校验
        ValidationUtils.notBlank(role.getCode(), "角色编码不能为空");
        
        ValidationUtils.notBlank(role.getName(), "角色名称不能为空");
        
        // ✅ 修复：移除 try-catch，避免重复日志，全局异常处理器会统一记录异常
        
        // 检查角色编码是否已存在
        if (existsByCode(role.getCode(), null)) {
            throw BusinessException.dataExists("角色编码已存在：" + role.getCode());
        }
        
        // 检查角色名称是否已存在
        if (existsByName(role.getName(), null)) {
            throw BusinessException.dataExists("角色名称已存在：" + role.getName());
        }
        
        // 设置默认值
        role.setId(UUID.randomUUID().toString());
        
        if (role.getStatus() == null) {
            role.setStatus(StatusEnum.ENABLED.getValue()); // 默认启用
        }
        
        if (!StringUtils.hasText(role.getDataScope())) {
            role.setDataScope("SELF"); // 默认仅自己
        }
        
        // 插入数据库
        roleMapper.insert(role);
        
        logger.info("创建角色成功: roleId={}, roleCode={}, roleName={}, tenantId={}", 
                   role.getId(), role.getCode(), role.getName(), role.getTenantId());
        
        return role;
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Role updateRole(String roleId, Role role) {
        if (!StringUtils.hasText(roleId) || role == null) {
            throw new IllegalArgumentException("角色ID和角色信息不能为空");
        }
        
        // 统一由租户拦截器处理租户字段，不在此处做必填校验
        
        // ✅ 修复：移除 try-catch，避免重复日志，全局异常处理器会统一记录异常
        
        // 查询现有角色
        Role existingRole = getRoleById(roleId);
        if (existingRole == null) {
            throw BusinessException.resourceNotFound("角色不存在：" + roleId);
        }
        
        // 检查角色编码是否已存在（排除当前角色）
        if (StringUtils.hasText(role.getCode()) && !role.getCode().equals(existingRole.getCode())) {
            if (existsByCode(role.getCode(), roleId)) {
                throw BusinessException.dataExists("角色编码已存在：" + role.getCode());
            }
        }
        
        // 检查角色名称是否已存在（排除当前角色）
        if (StringUtils.hasText(role.getName()) && !role.getName().equals(existingRole.getName())) {
            if (existsByName(role.getName(), roleId)) {
                throw BusinessException.dataExists("角色名称已存在：" + role.getName());
            }
        }
        
        // 更新角色信息
        LambdaUpdateWrapper<Role> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(Role::getId, roleId);
        
        if (StringUtils.hasText(role.getCode())) {
            updateWrapper.set(Role::getCode, role.getCode());
        }
        if (StringUtils.hasText(role.getName())) {
            updateWrapper.set(Role::getName, role.getName());
        }
        if (role.getStatus() != null) {
            updateWrapper.set(Role::getStatus, role.getStatus());
        }
        if (StringUtils.hasText(role.getDescription())) {
            updateWrapper.set(Role::getDescription, role.getDescription());
        }
        if (StringUtils.hasText(role.getDataScope())) {
            updateWrapper.set(Role::getDataScope, role.getDataScope());
        }
        
        int updated = roleMapper.update(null, updateWrapper);
        if (updated > 0) {
            // 查询更新后的角色信息
            Role updatedRole = getRoleById(roleId);
            
            logger.info("更新角色成功: roleId={}, roleCode={}, roleName={}, tenantId={}", 
                       roleId, role.getCode(), role.getName(), role.getTenantId());
            return updatedRole;
        } else {
            throw BusinessException.operationFailed("更新角色失败，可能角色不存在或已被删除");
        }
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteRole(String roleId) {
        if (!StringUtils.hasText(roleId)) {
            return false;
        }
        
        // ✅ 修复：移除外层 try-catch，避免重复日志，全局异常处理器会统一记录异常
        
        // 检查角色是否存在
        Role existingRole = getRoleById(roleId);
        if (existingRole == null) {
            throw BusinessException.resourceNotFound("要删除的角色不存在");
        }
        
        String currentTenantId = com.kexio.auth.context.TenantContextHolder.getTenant();
        // 检查角色是否被使用
        if (isRoleInUse(roleId, currentTenantId)) {
            throw BusinessException.operationFailed("角色正在被使用，无法删除");
        }
        
        // 删除角色权限关联（如果失败会抛异常，事务回滚确保数据一致性）
        deleteRolePermissions(roleId);
        logger.info("已删除角色权限关联: roleId={}", roleId);
        
        // 逻辑删除角色，使用 @TableLogic
        int deleted = roleMapper.deleteById(roleId);
        
        if (deleted > 0) {
            logger.info("删除角色成功: roleId={}, roleCode={}", 
                       roleId, existingRole.getCode());
            return true;
        }
        
        return false;
    }
    
    @Override
    public Role getRoleById(String roleId) {
        if (!StringUtils.hasText(roleId)) {
            return null;
        }
        
        // ✅ 修复：移除不必要的 try-catch，让异常自然抛出
        // 数据库异常会被全局异常处理器捕获
        LambdaQueryWrapper<Role> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Role::getId, roleId);
        
        return roleMapper.selectOne(queryWrapper);
    }
    
    @Override
    public Role getRoleByCode(String roleCode) {
        if (!StringUtils.hasText(roleCode)) {
            return null;
        }
        
        // ✅ 修复：移除不必要的 try-catch，让异常自然抛出
        LambdaQueryWrapper<Role> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Role::getCode, roleCode);
        
        return roleMapper.selectOne(queryWrapper);
    }
    
    @Override
    public Page<Role> getRolePage(Long current, Long size) {
        // ✅ 修复：移除不必要的 try-catch，让异常自然抛出
        Page<Role> page = new Page<>(
            com.kexio.common.page.PageUtils.normalizePageNo(current),
            com.kexio.common.page.PageUtils.normalizePageSize(size)
        );
        
        LambdaQueryWrapper<Role> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.orderByDesc(Role::getCreateTime);
        
        return roleMapper.selectPage(page, queryWrapper);
    }
    
    @Override
    public Page<Role> getRolePage(Long current, Long size, String roleCode, String roleName, Integer status) {
        // ✅ 修复：移除不必要的 try-catch，让异常自然抛出
        Page<Role> page = new Page<>(
            com.kexio.common.page.PageUtils.normalizePageNo(current),
            com.kexio.common.page.PageUtils.normalizePageSize(size)
        );
        
        LambdaQueryWrapper<Role> queryWrapper = new LambdaQueryWrapper<>();
        
        // 添加条件查询
        if (StringUtils.hasText(roleCode)) {
            queryWrapper.like(Role::getCode, roleCode);
        }
        if (StringUtils.hasText(roleName)) {
            queryWrapper.like(Role::getName, roleName);
        }
        if (status != null) {
            queryWrapper.eq(Role::getStatus, status);
        }
        
        queryWrapper.orderByDesc(Role::getCreateTime);
        
        Page<Role> rolePage = roleMapper.selectPage(page, queryWrapper);
        
        logger.debug("带条件分页查询角色成功: current={}, size={}, roleCode={}, roleName={}, status={}, total={}", 
                    current, size, roleCode, roleName, status, rolePage.getTotal());
        
        return rolePage;
    }
    
    @Override
    public List<Role> getAllRoles() {
        // ✅ 修复：移除不必要的 try-catch，让异常自然抛出
        LambdaQueryWrapper<Role> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.orderByDesc(Role::getCreateTime);
        
        return roleMapper.selectList(queryWrapper);
    }
    
    @Override
    public List<Role> getActiveRoles() {
        // ✅ 修复：移除不必要的 try-catch，让异常自然抛出
        LambdaQueryWrapper<Role> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper
                    .eq(Role::getStatus, 1)
                    .orderByDesc(Role::getCreateTime);
        
        return roleMapper.selectList(queryWrapper);
    }
    
    @Override
    public List<Role> getRolesByStatus(String status) {
        if (!StringUtils.hasText(status)) {
            return Collections.emptyList();
        }
        
        // ✅ 修复：移除不必要的 try-catch，让异常自然抛出
        LambdaQueryWrapper<Role> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper
                    .eq(Role::getStatus, Integer.valueOf(status))
                    .orderByDesc(Role::getCreateTime);
        
        return roleMapper.selectList(queryWrapper);
    }
    
    @Override
    public List<Permission> getRolePermissions(String roleId) {
        if (!StringUtils.hasText(roleId)) {
            return Collections.emptyList();
        }
        
        // ✅ 修复：移除不必要的 try-catch，让异常自然抛出
        return roleMapper.selectRolePermissions(roleId);
    }
    
    @Override
    public List<String> getRolePermissionCodes(String roleId) {
        if (!StringUtils.hasText(roleId)) {
            return Collections.emptyList();
        }
        
        // ✅ 修复：移除不必要的 try-catch，让异常自然抛出
        return roleMapper.selectRolePermissionCodes(roleId);
    }
    
    @Override
    public boolean assignPermissions(String roleId, List<String> permissionIds, String operatorId) {
        if (!StringUtils.hasText(roleId)) {
            return false;
        }
        
        // ✅ 修复：移除外层 try-catch，让异常自然抛出以确保事务回滚
        if (rolePermissionMapper == null) {
            logger.warn("RolePermissionMapper 未注入，跳过赋权");
            return false;
        }
        
        String currentTenantId = com.kexio.auth.context.TenantContextHolder.getTenant();
        java.util.HashMap<String, Object> params = new java.util.HashMap<>();
        params.put("roleId", roleId);
        params.put("tenantId", currentTenantId);
        params.put("permissionIds", permissionIds);
        Long createdBy = null;
        try { createdBy = operatorId != null ? Long.valueOf(operatorId) : null; } catch (NumberFormatException ignore) {}
        params.put("createdBy", createdBy != null ? createdBy : 1L);
        rolePermissionMapper.syncRolePermissions(params);
        
        // 🚀 实时同步角色权限变更，影响所有拥有该角色的用户
        // ✓ 保留内部 catch：同步失败不影响主流程
        if (permissionSyncService != null) {
            try {
                permissionSyncService.syncRolePermissions(roleId, currentTenantId, "权限分配变更");
                logger.info("🔄 角色权限实时同步完成: roleId={}", roleId);
            } catch (Exception e) {
                logger.warn("角色权限同步失败，但权限分配成功: roleId={}, error={}", roleId, e.getMessage());
            }
        }
        
        // ✅ 新增：批量更新该角色下所有用户的权限版本号
        // ✓ 保留内部 catch：版本更新失败不影响主流程
        if (permVersionService != null) {
            try {
                int affectedUsers = permVersionService.onRolePermissionChanged(roleId);
                logger.info("✅ 角色权限分配，批量更新用户权限版本: roleId={}, affectedUsers={}", roleId, affectedUsers);
            } catch (Exception e) {
                logger.warn("⚠️ 批量更新用户权限版本失败: roleId={}, error={}", roleId, e.getMessage());
            }
        }
        
        return true;        
    }
    
    @Override
    public boolean removePermissions(String roleId, List<String> permissionIds) {
        if (!StringUtils.hasText(roleId) || CollectionUtils.isEmpty(permissionIds)) {
            return false;
        }
        
        // ✅ 修复：移除 try-catch，让异常自然抛出以确保事务回滚
        if (rolePermissionMapper == null) {
            return false;
        }
        
        String currentTenantId = com.kexio.auth.context.TenantContextHolder.getTenant();
        java.util.HashMap<String, Object> params = new java.util.HashMap<>();
        params.put("roleId", roleId);
        params.put("tenantId", currentTenantId);
        params.put("permissionIds", permissionIds);
        rolePermissionMapper.batchDeleteByRoleAndPermissions(params);
        
        return true;
    }
    
    @Override
    public boolean syncPermissions(String roleId, List<String> permissionIds, Long operatorId) {
        if (!StringUtils.hasText(roleId)) {
            return false;
        }
        
        // ✅ 修复：移除外层 try-catch，让异常自然抛出以确保事务回滚
        if (rolePermissionMapper == null) {
            return false;
        }
        
        String currentTenantId = com.kexio.auth.context.TenantContextHolder.getTenant();
        java.util.HashMap<String, Object> params = new java.util.HashMap<>();
        params.put("roleId", roleId);
        params.put("tenantId", currentTenantId);
        params.put("permissionIds", permissionIds);
        params.put("createdBy", operatorId != null ? operatorId : 1L);
        rolePermissionMapper.syncRolePermissions(params);
        
        // ✅ 新增：批量更新该角色下所有用户的权限版本号
        // ✓ 保留内部 catch：版本更新失败不影响主流程
        if (permVersionService != null) {
            try {
                int affectedUsers = permVersionService.onRolePermissionChanged(roleId);
                logger.info("✅ 角色权限同步，批量更新用户权限版本: roleId={}, affectedUsers={}", roleId, affectedUsers);
            } catch (Exception e) {
                logger.warn("⚠️ 批量更新用户权限版本失败: roleId={}, error={}", roleId, e.getMessage());
            }
        }
        
        return true;
    }
    
    @Override
    public List<User> getRoleUsers(String roleId) {
        if (!StringUtils.hasText(roleId)) {
            return Collections.emptyList();
        }
        
        // ✅ 修复：移除不必要的 try-catch，让异常自然抛出
        return roleMapper.selectRoleUsers(roleId);
    }
    
    @Override
    public List<Role> getUserRoles(String userId) {
        if (!StringUtils.hasText(userId)) {
            return Collections.emptyList();
        }
        
        // ✅ 修复：移除不必要的 try-catch，让异常自然抛出
        return roleMapper.selectUserRoles(userId);
    }
    
    @Override
    public boolean assignUsers(String roleId, List<String> userIds, Long operatorId) {
        if (!StringUtils.hasText(roleId) || CollectionUtils.isEmpty(userIds)) {
            return false;
        }
        
        // ✅ 修复：移除 try-catch，让异常自然抛出以确保事务回滚
        if (userRoleMapper == null) {
            return false;
        }
        
        String createdBy = operatorId != null ? String.valueOf(operatorId) : "1";
        userRoleMapper.batchAssignUsers(roleId, userIds, createdBy);
        
        return true;
    }
    
    @Override
    public boolean removeUsers(String roleId, List<String> userIds) {
        if (!StringUtils.hasText(roleId) || CollectionUtils.isEmpty(userIds)) {
            return false;
        }
        
        // ✅ 修复：移除 try-catch，让异常自然抛出以确保事务回滚
        if (userRoleMapper == null) {
            return false;
        }
        
        userRoleMapper.batchDeleteByRoleAndUsers(roleId, userIds);
        return true;
    }
    
    @Override
    public boolean syncUsers(String roleId, List<String> userIds, Long operatorId) {
        if (!StringUtils.hasText(roleId)) {
            return false;
        }
        
        // ✅ 修复：移除 try-catch，让异常自然抛出以确保事务回滚
        if (userRoleMapper == null) {
            return false;
        }
        
        String createdBy = operatorId != null ? String.valueOf(operatorId) : "1";
        userRoleMapper.syncRoleUsers(roleId, userIds, createdBy);
        
        return true;
    }
    
    @Override
    public List<Menu> getRoleMenus(String roleId, String tenantId) {
        if (!StringUtils.hasText(roleId)) {
            return Collections.emptyList();
        }
        
        // ✅ 修复：移除不必要的 try-catch，让异常自然抛出
        return roleMapper.selectRoleMenus(roleId);
    }
    
    @Override
    public List<Menu> getRoleMenuTree(String roleId, String tenantId) {
        // 暂返回平铺列表；如需树形可在后续组装
        return getRoleMenus(roleId, tenantId);
    }
    
    @Override
    public boolean assignMenus(String roleId, List<String> menuIds, String operatorId) {
        if (!StringUtils.hasText(roleId)) {
            logger.warn("分配角色菜单参数无效: roleId={}", roleId);
            return false;
        }
        
        // 注意：tenantId由MyBatis-Plus自动填充处理，这里不需要手动获取和校验
        
        // 验证角色是否存在
        Role role = getRoleById(roleId);
        if (role == null) {
            throw BusinessException.resourceNotFound("角色不存在");
        }
        
        // 先删除角色现有的所有菜单关联
        roleMapper.deleteRoleMenusByRoleId(roleId);
        
        // 如果菜单ID列表不为空，则插入新的关联关系
        if (menuIds != null && !menuIds.isEmpty()) {
            // 过滤掉空的菜单ID
            List<String> validMenuIds = menuIds.stream()
                    .filter(StringUtils::hasText)
                    .collect(Collectors.toList());
            
            if (!validMenuIds.isEmpty()) {
                // 创建RoleMenu对象列表
                List<RoleMenu> roleMenus = validMenuIds.stream()
                        .map(menuId -> {
                            RoleMenu rm = new RoleMenu();
                            rm.setId(UUID.randomUUID().toString().replace("-", "")); // 生成32位UUID
                            rm.setRoleId(roleId);
                            rm.setMenuId(menuId);
                            // tenantId、createBy、updateBy字段由MyBatis-Plus自动填充
                            // 注意：createBy和updateBy字段可能由MyBatis-Plus自动填充
                            // 如果需要设置，需要将String转换为Long或使用其他机制
                            rm.setCreateBy(null); // 留空，让MyBatis-Plus自动填充
                            rm.setUpdateBy(null); // 留空，让MyBatis-Plus自动填充
                            rm.setCreateTime(LocalDateTime.now());
                            rm.setUpdateTime(LocalDateTime.now());
                            return rm;
                        })
                        .collect(Collectors.toList());
                
                // 批量插入角色菜单关联
                int inserted = roleMapper.batchInsertRoleMenus(roleMenus);
                logger.info("为角色分配菜单: roleId={}, menuCount={}, inserted={}", 
                          roleId, validMenuIds.size(), inserted);
            }
        }
        
        // ✅ 批量更新该角色下所有用户的权限版本号（菜单变更影响路由）
        // ✓ 保留内部 catch：版本更新失败不影响主流程
        if (permVersionService != null) {
            try {
                int affectedUsers = permVersionService.onRolePermissionChanged(roleId);
                logger.info("✅ 角色菜单分配，批量更新用户权限版本: roleId={}, affectedUsers={}", roleId, affectedUsers);
            } catch (Exception e) {
                logger.warn("⚠️ 批量更新用户权限版本失败: roleId={}, error={}", roleId, e.getMessage());
            }
        }
        
        logger.info("角色菜单分配成功: roleId={}, menuCount={}", 
                  roleId, menuIds != null ? menuIds.size() : 0);
        
        return true;
    }
    
    @Override
    public Object getRoleDataScope(String roleId, String tenantId) {
        if (!StringUtils.hasText(roleId)) {
            return null;
        }
        
        Map<String, Object> scopeInfo = new HashMap<>();
        scopeInfo.put("roleId", roleId);
        scopeInfo.put("tenantId", tenantId);
        scopeInfo.put("scopeType", "ALL");  // 简化后的默认权限
        scopeInfo.put("description", "JWT架构下数据权限已简化");
        return scopeInfo;
        

    }
    
    @Override
    public List<Object> getUserDataScope(String userId, String tenantId) {
        if (!StringUtils.hasText(userId)) {
            return Collections.emptyList();
        }

        Map<String, Object> userScope = new HashMap<>();
        userScope.put("userId", userId);
        userScope.put("tenantId", tenantId);
        userScope.put("scopeType", "ALL");  // 简化后的默认权限
        userScope.put("description", "JWT架构下数据权限已简化");
        return Collections.singletonList(userScope);

    }
    
    @Override
    public boolean updateDataScope(String roleId, String dataScope, List<String> deptIds, String tenantId, Long operatorId) {
        if (!StringUtils.hasText(roleId) || !StringUtils.hasText(dataScope)) {
            return false;
        }
        
        // ✅ 修复：移除 try-catch，让异常自然抛出以确保事务回滚
        LambdaUpdateWrapper<Role> uw = new LambdaUpdateWrapper<>();
        uw.eq(Role::getId, roleId);
        uw.set(Role::getDataScope, dataScope);
        if (deptIds != null && !deptIds.isEmpty()) {
            String csv = deptIds.stream().map(String::valueOf).reduce((a,b) -> a+","+b).orElse("");
            uw.set(Role::getCustomDeptIds, csv);
        } else {
            uw.set(Role::getCustomDeptIds, null);
        }
        int updated = roleMapper.update(null, uw);
        
        return updated > 0;
    }
    
    @Override
    public List<Role> getChildRoles(Long parentRoleId, String tenantId) {
        if (parentRoleId == null) {
            return Collections.emptyList();
        }
        
        // ✅ 修复：移除不必要的 try-catch，让异常自然抛出
        return roleMapper.selectChildRoles(parentRoleId);
    }
    
    @Override
    public List<Role> getAncestorRoles(String roleId, String tenantId) {
        if (!StringUtils.hasText(roleId)) {
            return Collections.emptyList();
        }
        
        // ✅ 修复：移除不必要的 try-catch，让异常自然抛出
        return roleMapper.selectAncestorRoles(roleId);
    }
    
    @Override
    public List<Role> getDescendantRoles(String roleId, String tenantId) {
        if (!StringUtils.hasText(roleId)) {
            return Collections.emptyList();
        }
        
        // ✅ 修复：移除不必要的 try-catch，让异常自然抛出
        return roleMapper.selectDescendantRoles(roleId);
    }
    
    @Override
    public boolean hasPermission(String roleId, String permissionCode, String tenantId) {
        if (!StringUtils.hasText(roleId) || !StringUtils.hasText(permissionCode)) {
            return false;
        }
        
        // ✅ 修复：移除不必要的 try-catch，让异常自然抛出
        // 如果数据库查询失败，应该抛出异常而不是默默返回 false
        List<String> codes = roleMapper.selectRolePermissionCodes(roleId);
        return codes != null && codes.contains(permissionCode);
    }
    
    @Override
    public boolean hasAnyPermission(String roleId, List<String> permissionCodes, String tenantId) {
        if (!StringUtils.hasText(roleId) || CollectionUtils.isEmpty(permissionCodes)) {
            return false;
        }
        
        // ✅ 修复：移除 try-catch，让异常自然抛出
        // 数据库查询失败应该抛出异常，而不是返回 false
        List<String> codes = roleMapper.selectRolePermissionCodes(roleId);
        if (codes == null || codes.isEmpty()) {
            return false;
        }
        
        for (String c : permissionCodes) {
            if (codes.contains(c)) return true;
        }
        
        return false;
    }
    
    @Override
    public boolean hasRole(String userId, String roleCode, String tenantId) {
        if (!StringUtils.hasText(userId) || !StringUtils.hasText(roleCode)) {
            return false;
        }
        
        // ✅ 修复：移除 try-catch，让异常自然抛出
        // 数据库查询失败应该抛出异常，而不是返回 false
        
        // 优先使用 UserRoleMapper 的 XML 查询：基于 roleCode 校验是否存在
        if (userRoleMapper != null) {
            return userRoleMapper.existsUserRole(userId, roleCode);
        }
        
        // 降级：查询用户角色列表后判断
        List<Role> roles = roleMapper.selectUserRoles(userId);
        if (CollectionUtils.isEmpty(roles)) {
            return false;
        }
        
        for (Role r : roles) {
            if (r != null && roleCode.equals(r.getCode())) {
                return true;
            }
        }
        
        return false;
    }
    
    @Override
    public Long countRolesByTenant(String tenantId) {
        return roleMapper.countRolesByTenant();
    }
    
    @Override
    public Long countActiveRoles(String tenantId) {
        return roleMapper.countActiveRoles();
    }
    
    @Override
    public Long countRoleUsers(String roleId, String tenantId) {
        return userRoleMapper != null ? userRoleMapper.countByRoleIdAndTenant(roleId) : 0L;
    }
    
    @Override
    public boolean existsByCode(String roleCode, String excludeRoleId) {
        if (!StringUtils.hasText(roleCode)) {
            return false;
        }
        
        // ✅ 修复：移除 try-catch，让异常自然抛出
        // 注意：如果系统启用多租户，tenantId由MyBatis拦截器自动处理
        
        LambdaQueryWrapper<Role> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Role::getCode, roleCode);
        
        if (StringUtils.hasText(excludeRoleId)) {
            queryWrapper.ne(Role::getId, excludeRoleId);
        }
        
        Long count = roleMapper.selectCount(queryWrapper);
        return count != null && count > 0;
    }
    
    @Override
    public boolean existsByName(String roleName, String excludeRoleId) {
        if (!StringUtils.hasText(roleName)) {
            return false;
        }
        
        // ✅ 修复：移除 try-catch，让异常自然抛出
        // 注意：如果系统启用多租户，tenantId由MyBatis拦截器自动处理
        
        LambdaQueryWrapper<Role> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Role::getName, roleName);
        
        if (StringUtils.hasText(excludeRoleId)) {
            queryWrapper.ne(Role::getId, excludeRoleId);
        }
        
        Long count = roleMapper.selectCount(queryWrapper);
        return count != null && count > 0;
    }
    
    @Override
    public boolean isRoleInUse(String roleId, String tenantId) {
        if (!StringUtils.hasText(roleId) || !StringUtils.hasText(tenantId)) {
            return false;
        }
        
        // ✅ 修复：移除 try-catch，让异常自然抛出
        // 检查是否有用户分配了此角色
        // 真正实现角色用户数量统计
        long userCount = getUserCountByRole(roleId, tenantId);
        return userCount > 0;
    }
    
    @Override
    public java.util.Map<String, Long> getRoleDistributionStats() {
        // ✅ 修复：移除 try-catch，让异常自然抛出
        // ✅ 批量查询所有角色及其用户数量（一条SQL搞定）
        List<java.util.Map<String, Object>> rawStats = roleMapper.selectRoleDistributionStats();
        java.util.Map<String, Long> distribution = new java.util.HashMap<>();
        
        if (rawStats != null && !rawStats.isEmpty()) {
            for (java.util.Map<String, Object> stat : rawStats) {
                Object roleNameObj = stat.get("role_name");
                Object userCountObj = stat.get("user_count");
                
                if (roleNameObj != null) {
                    String roleName = String.valueOf(roleNameObj);
                    long userCount = 0L;
                    if (userCountObj instanceof Number) {
                        userCount = ((Number) userCountObj).longValue();
                    }
                    distribution.put(roleName, userCount);
                }
            }
        }
        
        return distribution.isEmpty() ? java.util.Map.of("无角色数据", 0L) : distribution;
    }

    
    /**
     * 统计角色下的用户数量
     */
    private long getUserCountByRole(String roleId, String tenantId) {
        // ✅ 修复：移除 try-catch，让异常自然抛出
        if (userRoleMapper != null) {
            return userRoleMapper.countByRoleIdAndTenant(roleId);
        }
        return 0L;
    }
    
    /**
     * 删除角色的所有权限关联
     */
    private void deleteRolePermissions(String roleId) {
        if (rolePermissionMapper != null) {
            com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<RolePermission> qw =
                    new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<>();
            qw.eq(RolePermission::getRoleId, roleId);
            int affected = rolePermissionMapper.delete(qw);
            logger.info("删除角色权限关联成功: roleId={}, affected={}", roleId, affected);
        }
    }
}
